home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Src / submit / submit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  11.3 KB  |  599 lines

  1. /* submit.c: the mail enqueuer */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/submit.c,v 6.0 1991/12/18 20:28:02 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Src/submit/RCS/submit.c,v 6.0 1991/12/18 20:28:02 jpo Rel $
  9.  *
  10.  * $Log: submit.c,v $
  11.  * Revision 6.0  1991/12/18  20:28:02  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include "head.h"
  19. #include "prm.h"
  20. #include "q.h"
  21. #include "or.h"
  22. #include <varargs.h>
  23. #include <sys/stat.h>
  24. #include <sys/time.h>
  25. #include <signal.h>
  26. #include <pwd.h>
  27. #include <isode/cmd_srch.h>
  28.  
  29.  
  30.  
  31. /* -- externals -- */
  32. extern char    *msg_unique,    /* unique part of msg queue name  */
  33.         *mgt_inhost,
  34.         *qmgr_hostname,
  35.         *rcmd_srch(),
  36.         *quedfldir,    /* dir w/mail queue directories */
  37.         auth2submit_msg[];
  38.  
  39. extern int           mgt_adtype,
  40.         protocol_mode;
  41.  
  42. ADDR        *ad_originator,
  43.         *ad_recip;
  44.  
  45. extern struct passwd    *getpwuid();
  46. extern long        msg_size;
  47. extern CHAN        *ch_inbound;
  48. extern CMD_TABLE    qtbl_mt_type[];
  49.  
  50.  
  51.  
  52.  
  53. /* -- globals -- */
  54. char    *username;    /* login name of usr running me */
  55. int    effecid,    /* id providing access priviliges */
  56.     privileged,    /* am I a priveledged user ? */
  57.     userid,        /* id of user running me */
  58.     accept_all,
  59.     submit_debug = 0,
  60.     notrace;
  61. Q_struct        Qstruct, *qptr;
  62.  
  63.  
  64.  
  65.  
  66. /* -- static variables    -- */
  67. static struct prm_vars    Prm;
  68. static int        qmgr_fd = NOTOK;
  69. static int        log_msgtype;
  70. static int        adr_count;
  71.  
  72. extern void fmt_init ();
  73. extern int validate_recip ();
  74. extern void auth_start ();
  75. extern void gen_warnings ();
  76. extern void gen_probedr ();
  77. extern void gen_ndr ();
  78. extern void auth_log ();
  79. extern void ad_init ();
  80. extern void check_splitter ();
  81. extern void check_conversions ();
  82. extern void check_report_level ();
  83. extern void check_crits ();
  84. extern void check_dr_crits ();
  85. extern void msg_mgt ();
  86. extern void time_mgt ();
  87. extern void clear_q ();
  88. extern int move_q ();
  89. extern int winit_q ();
  90. extern int write_q ();
  91. extern void txt_input ();
  92. extern void ad_log_print ();
  93. extern ADDR *read_sender ();
  94. extern ADDR *read_recipient ();
  95. extern int         server_start ();
  96.  
  97. /* -- local routines -- */
  98. void            err_abrt();
  99. void            pro_reply();
  100.  
  101. static int        priv_user();
  102. static void        _pro_reply();
  103. static void        dir_init();
  104. static void        done();
  105. static void        msg_init();
  106. static void        user_init();
  107.  
  108.  
  109.  
  110. /*  --------------------  Main    Routine     ---------------------------------- */
  111.  
  112.  
  113.  
  114. /* ARGSUSED */
  115. main (argc, argv)
  116. int        argc;
  117. char        **argv;
  118. {
  119.     int    retval;
  120.     int    qmgr_status;
  121.     int    server = 0;
  122.     ADDR    *ad;
  123.     ADDR    **app;
  124.     RP_Buf rps, *rp = &rps;
  125.     int opt;
  126.     extern char *optarg, *pptailor;
  127.  
  128.     while ((opt = getopt (argc, argv, "dst:")) != EOF) {
  129.         switch (opt) {
  130.             case 'd':
  131.             submit_debug = 1;
  132.             break;
  133.             case 's':
  134.             server = 1;
  135.             break;
  136.             case 't':
  137.             pptailor = optarg;
  138.             break;
  139.         }
  140.     }
  141.  
  142.     (void) umask (0);
  143.     sys_init (argv[0]);
  144.  
  145.     qptr = &Qstruct;
  146.     q_init (qptr);
  147.  
  148.     user_init();
  149.     dir_init();
  150.     or_myinit();
  151.     fmt_init();
  152.  
  153.     (void) signal (SIGPIPE, done);
  154.     if (server)
  155.         qmgr_fd = server_start (qmgr_hostname, &qmgr_status);
  156.     else
  157.         qmgr_fd = qmgr_start (qmgr_hostname, &qmgr_status, 1);
  158.  
  159. #define pp_could_go_faster 1
  160.     while (pp_could_go_faster) { /* infinite loop! */
  161.  
  162.         /*
  163.             Reset various parameters
  164.         */
  165.         msg_init();
  166.  
  167.         protocol_mode = 1;
  168.  
  169.  
  170.         /*
  171.             Read the parameter settings for a Message
  172.         */
  173.         if (rp_isbad (retval = rd_prm_info (&Prm))) {
  174.             if (retval == RP_EOF)
  175.                 break; /* we're done */
  176.             err_abrt (retval, "bad parameters");
  177.         }
  178.         else
  179.             pro_reply (RP_OK, "Got the parameters");
  180.  
  181.         if (qmgr_status != DONE && qmgr_fd != NOTOK)
  182.             qmgr_fd = qmgr_retry (qmgr_fd, &qmgr_status);
  183.         /*
  184.             Read the queue structure
  185.         */
  186.         if (rp_isbad (retval = rd_q_info (qptr)))
  187.             err_abrt (retval, "Bad queue read");
  188.  
  189.         /*
  190.             Perform management functions on parameters
  191.         */
  192.         if (rp_isbad (retval = cntrl_mgt (&Prm, qptr)))
  193.             err_abrt (retval, "Bad parameter settings");
  194.  
  195.         /*
  196.             Perform management functions on the queue
  197.         */
  198.         if (rp_isbad (retval = q_mgt (qptr)))
  199.             err_abrt (retval, "Bad queue parameter settings");
  200.  
  201.         pro_reply (RP_OK, "Starting fine, sender please");
  202.  
  203.         /*
  204.          * read and validate the sender
  205.          */
  206.  
  207.         ad = read_sender (qptr);
  208.         if (validate_sender(qptr, ad, username, rp) != RP_OK)
  209.             err_abrt (rp -> rp_val, "%s", rp -> rp_line);
  210.         ad_originator = ad;
  211.  
  212.         pro_reply (RP_AOK, "Continuing fine, addresses please");
  213.  
  214.         if (qmgr_status != DONE && qmgr_fd != NOTOK)
  215.             qmgr_fd = qmgr_retry (qmgr_fd, &qmgr_status);
  216.  
  217.         /*
  218.          * Read and validate the recipients.
  219.          */
  220.  
  221.         app = &ad_recip;
  222.         while ((ad = read_recipient (qptr)) != NULLADDR) {
  223.             if (rp_isbad(validate_recip(ad, qptr, rp))) {
  224.                 if (rp_gbval (rp -> rp_val) == RP_BTNO &&
  225.                     retval != RP_BHST &&
  226.                     retval != RP_DHST)
  227.                     err_abrt (rp -> rp_val, "%s",
  228.                           rp -> rp_line);
  229.                 pro_reply (rp -> rp_val, "%s", rp -> rp_line);
  230.                 adr_tfree (ad);
  231.                 continue;
  232.             }
  233.             else
  234.                 pro_reply (rp -> rp_val, "%s", rp -> rp_line);
  235.             (*app) = ad; /* add to recipient list */
  236.             app = &(*app) -> ad_next;
  237.             adr_count ++;
  238.         }
  239.         if (ad_recip == NULLADDR)
  240.             err_abrt (RP_USER, "No valid addresses found");
  241.         ad_log_print (ad_recip);
  242.  
  243.         /*
  244.             Authorisation - main routines
  245.         */
  246.  
  247.         auth_start(qptr, ad_originator, ad_recip);
  248.  
  249.         /*
  250.             Sets the Qstruct's Originator and Recipient fields
  251.         */
  252.         qptr -> Oaddress = ad_originator;
  253.         qptr -> Raddress = ad_recip;
  254.         time_mgt(qptr);
  255.         /*
  256.             Initialize to the queue directory for output
  257.         */
  258.  
  259.         if (rp_isbad(winit_q(rp)))
  260.             err_abrt (rp -> rp_val, "%s", rp -> rp_line);
  261.  
  262.         /*
  263.             if (DMPDU)
  264.                 parse DR from incoming channel
  265.                 then get body (if any)
  266.             else if probe
  267.                 nothing much
  268.             else (normal message)
  269.                 splat the body into a file
  270.         */
  271.  
  272.         log_msgtype = qptr -> msgtype;
  273.  
  274.         switch (qptr -> msgtype) {
  275.         case MT_DMPDU:
  276.             pro_reply (RP_AOK, "Addresses ok, DR info please");
  277.             if (rp_isbad (retval = gen_io2dr(qptr))) {
  278.                 err_abrt (retval, "Bad DR struct");
  279.             }
  280.             pro_reply (RP_AOK, "DR OK");
  281.             txt_input (qptr, notrace == 0);
  282.             break;
  283.  
  284.         case MT_PMPDU:
  285.             msg_size = qptr -> msgsize; 
  286.             break;
  287.  
  288.         default:
  289.             pro_reply (RP_AOK, "Addresses ok, text please");
  290.             txt_input (qptr, notrace == 0);
  291.             break;
  292.         }
  293.  
  294.         if (qmgr_status != DONE && qmgr_fd != NOTOK)
  295.             qmgr_fd = qmgr_retry (qmgr_fd, &qmgr_status);
  296.  
  297.         protocol_mode = 0;    /* end of protocol phase */
  298.  
  299.         /*
  300.             finish authorisation tests on message
  301.             size/body parts and perform channel binding
  302.         */
  303.  
  304.         if (rp_isbad (retval = auth_finish(qptr, ad_originator,
  305.                            ad_recip)))
  306.             if (!accept_all)
  307.                 err_abrt (retval, "%s : %s",
  308.                 "At least one recipient fails authorisation",
  309.                 auth2submit_msg);
  310.         
  311.         check_splitter(qptr);
  312.         check_crits (qptr);
  313.         check_conversions (qptr);
  314.         check_report_level (qptr);
  315.         setup_directories (qptr);
  316.  
  317.         /*
  318.             Generate the appropriate Delivery Notifications 
  319.         */
  320.  
  321.         switch (qptr -> msgtype) {
  322.         case MT_PMPDU:
  323.             gen_probedr(qptr);
  324.             break;
  325.         default:
  326.             gen_ndr(qptr);
  327.             break;
  328.         }
  329.  
  330.         if (rp_isbad (write_q (qptr, &Prm, rp)) ||
  331.             rp_isbad (move_q(rp)))
  332.             err_abrt (rp -> rp_val, "%s", rp -> rp_line);
  333.  
  334.  
  335.         pro_reply (RP_MOK, "Submitted & queued (%s)", msg_unique);
  336.  
  337.  
  338.         /*
  339.             generate authorisation statistics logs
  340.             now that msg_unique is known
  341.         */
  342.  
  343.         auth_log(qptr, ad_originator, ad_recip, msg_unique);
  344.  
  345.         /* Tell qmgr */
  346.  
  347.         if (qmgr_fd != NOTOK)
  348.             tell_qmgr (msg_unique, &Prm, qptr, ad_originator,
  349.                    ad_recip, adr_count);
  350.         if (ch_inbound != NULL && ch_inbound->ch_access == CH_MTS)
  351.             PP_NOTICE (("<<< local %s %s %s %s %s",
  352.                     rcmd_srch(log_msgtype, qtbl_mt_type),
  353.                     msg_unique,
  354.                     ch_inbound -> ch_name,
  355.                     username, 
  356.                     mgt_inhost));
  357.         else
  358.             PP_NOTICE (("<<< remote %s %s %s %s", 
  359.                     rcmd_srch(log_msgtype, qtbl_mt_type),
  360.                     msg_unique,
  361.                     ch_inbound -> ch_name,
  362.                     mgt_inhost == NULLCP ? "<unknown-host>" :
  363.                     mgt_inhost));
  364.  
  365.         gen_warnings (qptr, ad_originator, ad_recip);
  366.     }
  367.  
  368.     if (qmgr_fd != NOTOK)
  369.         (void) qmgr_end (qmgr_fd);
  370.  
  371.     PP_TRACE (("Submit normal end"));
  372.     exit (0); /* NOTREACHED */
  373. }
  374.  
  375.  
  376. tell_qmgr (msg, prm, qp, sndr, recip, cnt)
  377. char    *msg;
  378. struct prm_vars *prm;
  379. Q_struct *qp;
  380. ADDR    *sndr, *recip;
  381. int cnt;
  382. {
  383.     if (qmgr_fd != NOTOK)
  384.         (void) message_send (qmgr_fd, msg, prm, qp, sndr, recip, cnt);
  385. }
  386.  
  387.  
  388. /*  --------------------  Static  Routines  ------------------------------- */
  389.  
  390.  
  391.  
  392.  
  393. /*
  394. Get information on the incomming channel calling submit
  395. */
  396.  
  397. static void user_init()
  398. {
  399.     register struct passwd *pw;
  400.  
  401.     PP_LOG (LLOG_DEBUG, ("submit/user_init()"));
  402.  
  403.     privileged = FALSE;
  404.     userid = getuid();
  405.     effecid = geteuid();
  406.  
  407.     if ((pw = getpwuid (userid)) == NULL)
  408.         err_abrt (RP_LIO,
  409.              "No login for UID %d, call Support.", userid);
  410.     endpwent();
  411.  
  412.     username = strdup (pw->pw_name);
  413.  
  414.     if (priv_user (userid, effecid) == TRUE)
  415.         privileged = TRUE;
  416.  
  417.     if (pp_setuserid() == NOTOK)
  418.         err_abrt (RP_LIO, "Unable to set user id");
  419. }
  420.  
  421. static int priv_user (id, eid)
  422. int    id, eid;
  423. {
  424.     struct passwd *pwd;
  425.     extern char *pplogin;
  426.  
  427.     if (id == 0 || eid == id)
  428.         return TRUE;
  429.  
  430.     if ((pwd = getpwnam (pplogin)) == (struct passwd *)0)
  431.         return FALSE;
  432.     if (id == pwd -> pw_uid)
  433.         return TRUE;
  434.     return FALSE;
  435. }
  436.  
  437.  
  438.  
  439. /*
  440. chdir
  441. */
  442.  
  443. static void dir_init()
  444. {
  445.     /*
  446.     cd into the queue directory
  447.     */
  448.     if (chdir (quedfldir) < 0)
  449.         err_abrt (RP_LIO, 
  450.             "Unable to change directory. '%s'", quedfldir);
  451. }
  452.  
  453.  
  454.  
  455.  
  456. /*
  457. Initialise a msg
  458. */
  459.  
  460. static void msg_init()
  461. {
  462.     msg_unique = NULLCP;    /* for logging failed messages */
  463.  
  464.     /*
  465.       address and qstruct 
  466.       done in two stages in case we filled in recipients but not
  467.       assigned to qstruct 
  468.      */
  469.     adr_count = 0;
  470.     if (ad_recip != NULLADDR)
  471.         adr_tfree (ad_recip);
  472.     if (ad_originator != NULLADDR)
  473.         adr_tfree (ad_originator);
  474.     ad_originator = NULLADDR;
  475.     ad_recip = NULLADDR;
  476.     qptr -> Oaddress = NULLADDR;
  477.     qptr -> Raddress = NULLADDR;
  478.     q_free (qptr);
  479.     msg_mgt();
  480. }
  481.  
  482. /*  --------------------  Reply     Routines  -------------------------------- */
  483.  
  484.  
  485.  
  486.  
  487. #ifdef lint
  488. /*VARARGS2*/
  489. void pro_reply (code, fmt)
  490. int code;
  491. char *fmt;
  492. {
  493.     pro_reply (code, fmt);
  494. }
  495. #else
  496. void pro_reply (va_alist)
  497. va_dcl
  498. {
  499.     va_list ap;
  500.     int    code;
  501.  
  502.     va_start(ap);
  503.  
  504.     code = va_arg (ap, int);
  505.  
  506.     _pro_reply (code, ap);
  507.  
  508.     va_end (ap);
  509. }
  510.  
  511. static void _pro_reply (code, ap)
  512. int    code;
  513. va_list ap;
  514. {
  515.     char    buffer[4*BUFSIZ];
  516.     register char  *errchar = NULLCP;
  517.  
  518.     if (rp_isbad (code))
  519.         switch (code) {
  520.             case RP_HUH: /* not if it was a user error */
  521.             case RP_PARM:
  522.             case RP_USER:
  523.             case RP_PARSE:
  524.             case RP_BHST:
  525.             case RP_NAUTH:
  526.             case RP_EOF:
  527.             break;
  528.  
  529.             default:
  530.             errchar = " ";
  531.             break;
  532.         }
  533.  
  534.     _asprintf (buffer, NULLCP, ap);
  535.  
  536.     if (rp_isbad (code))
  537.         PP_SLOG (LLOG_EXCEPTIONS, errchar,
  538.              ("submit/pro_reply(%s) '%s'", rp_valstr (code),
  539.               buffer));
  540.     else
  541.         PP_LOG (LLOG_PDUS|LLOG_TRACE,
  542.             ("submit/pro_reply(%s) '%s'", rp_valstr (code),
  543.              buffer));
  544.  
  545.     if (submit_debug)
  546.         printf ("%s:", rp_valstr(code));
  547.     else
  548.         (void) putc (code, stdout);
  549.  
  550.     (void) fputs (buffer, stdout);
  551.     (void) putc ('\n', stdout);
  552.     (void) fflush (stdout);
  553. }
  554. #endif
  555.  
  556. /* ---------------  (err_)  GENERAL ERROR-HANDLING  ----------------------- */
  557.  
  558.  
  559. #ifdef lint
  560. /*VARARGS2*/
  561. void err_abrt (code, fmt)
  562. int    code;
  563. char    *fmt;
  564. {
  565.     clear_q();
  566.  
  567.     pro_reply (code, fmt);
  568. }
  569. #else
  570. void err_abrt (va_alist)   /* terminate the process         */
  571. va_dcl
  572. {
  573.     va_list ap;
  574.     int    code;
  575.  
  576.     va_start (ap);
  577.  
  578.     code = va_arg (ap, int);
  579.  
  580.     PP_TRACE (("err_abrt (%d)", code));
  581.  
  582.     _pro_reply (code, ap);
  583.  
  584.     va_end (ap);
  585.  
  586.     done (-1);          /* pass the reply code to caller        */
  587. }
  588. #endif
  589.  
  590. static void done (n)
  591. int    n;
  592. {
  593.     PP_TRACE (("done (%d)", n));
  594.     clear_q();
  595.     if (qmgr_fd != NOTOK)
  596.         qmgr_end (qmgr_fd);
  597.     exit (n);
  598. }
  599.